#include <QApplication>
#include <QMainWindow>
#include <QAction>
#include <QAction>
#include <QMenuBar>
#include <QWidget>
#include <QToolBar>
#include <QPlainTextEdit>
#include <QFileDialog>
#include <QDockWidget>
#include <QLabel>
#include <QStatusBar>
#include <QGridLayout>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDesktopWidget>
#include <QCheckBox>
#include <QListWidget>
#include <QStackedWidget>
#include <QDir>
#include <QFont>
#include <QIcon>
#include <QStringList>
#include <QMessageBox>
#include <QDebug>
//for xml parse (must add "Qt += xml" to .pro file)
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <QDomNodeList>
//for stardard c++
#include <iostream>
using namespace std;

//#include "mainwindow.h"
#include "reciteword.h"
//#include "settingdialog.h"

//void ReciteWord::showTrans()
//{
//}
void ReciteWord::nextWord()
{
  knowBtn->setVisible(true);
  unknowBtn->setVisible(true);
  rightBtn->setVisible(false);
  wrongBtn->setVisible(false);
  nextBtn->setVisible(false);

  wordIndex = getWordIndex();
  wordLine->setText(dict.words[wordIndex].word);
  phoneticLabel->setText(dict.words[wordIndex].phonetic);
  transEdit->setText("");	//do not display trans & example
  exampleEdit->setText("");	
}
void ReciteWord::know()
{
  knowBtn->setVisible(false);
  unknowBtn->setVisible(false);
  rightBtn->setVisible(true);
  wrongBtn->setVisible(true);
  nextBtn->setVisible(false);
  
  transEdit->setText(dict.words[wordIndex].trans);
  exampleEdit->setText(dict.words[wordIndex].example);
  
  if(autoSpeechBox->isChecked())
    speech();
}
void ReciteWord::unKnow()
{
  bool remembered;

  knowBtn->setVisible(false);
  unknowBtn->setVisible(false);
  rightBtn->setVisible(false);
  wrongBtn->setVisible(false);
  nextBtn->setVisible(true);

  transEdit->setText(dict.words[wordIndex].trans);
  exampleEdit->setText(dict.words[wordIndex].example);
  
  if(autoSpeechBox->isChecked())
    speech();

  remembered = (dict.words[wordIndex].degree <= REMEMBERED_DEGREE);	//remembered or not 
    
  dict.words[wordIndex].degree *= 2;	//unknow
  if(dict.words[wordIndex].degree > MAX_DEGREE)
    dict.words[wordIndex].degree = MAX_DEGREE;
  
  //update statisticLabel
  if(remembered && (dict.words[wordIndex].degree > REMEMBERED_DEGREE) )	//remembered ago, but now forget
    {
      if(rememberedCnt)
	rememberedCnt--;
      statisticLabel->setText("Remembered : " + QString::number(rememberedCnt) + " / " + QString::number(dict.num)) ;
    }
  
}
void ReciteWord::knowWrong()
{
  bool remembered;
  /*  knowBtn->setVisible(true);
  unknowBtn->setVisible(true);
  rightBtn->setVisible(false);
  wrongBtn->setVisible(false);
  nextBtn->setVisible(false);
  */

  remembered = (dict.words[wordIndex].degree <= REMEMBERED_DEGREE);	//remembered or not 

  dict.words[wordIndex].degree *= 1.5;	//know, but error
  if(dict.words[wordIndex].degree > MAX_DEGREE)
    dict.words[wordIndex].degree = MAX_DEGREE;

  //update statisticLabel
  if(remembered && (dict.words[wordIndex].degree > REMEMBERED_DEGREE) )	//remembered ago, but now forget
    {
      if(rememberedCnt)
	rememberedCnt--;
      statisticLabel->setText("Remembered : " + QString::number(rememberedCnt) + " / " + QString::number(dict.num)) ;
    }
  nextWord();
}
void ReciteWord::knowRight()
{
  bool remembered;
  /*
  knowBtn->setVisible(true);
  unknowBtn->setVisible(true);
  rightBtn->setVisible(false);
  wrongBtn->setVisible(false);
  nextBtn->setVisible(false);
  */

  remembered = (dict.words[wordIndex].degree <= REMEMBERED_DEGREE);	//remembered or not 

  dict.words[wordIndex].degree /= 2;	//know, and right
  if(dict.words[wordIndex].degree < MIN_DEGREE)	//should >= MIN_DEGREE
    dict.words[wordIndex].degree = MIN_DEGREE;

  //update statisticLabel
  if(!remembered && (dict.words[wordIndex].degree <= REMEMBERED_DEGREE) )	//not remembered ago, but now remembered
    {
      rememberedCnt++;
      statisticLabel->setText("Remembered : " + QString::number(rememberedCnt) + " / " + QString::number(dict.num)) ;
    }
  nextWord();
}

void ReciteWord::speech()
{
  cout << "speech" << endl;
}

void ReciteWord::showExampleEdit(bool checked)
{
  configFile.showexample = checked;
  exampleEdit->setVisible(checked);
}
void ReciteWord::setAutoSpeech(bool checked)
{
  configFile.autospeech = checked;
}
void ReciteWord::backupConfig()
{
  configFileBak.dictfile = configFile.dictfile;
  configFileBak.speechpath = configFile.speechpath;
  configFileBak.autospeech = configFile.autospeech;
  configFileBak.showexample = configFile.showexample;
}

int ReciteWord::record()
{
  //if(initOK() == false)	//check while call this function
  //return 0;

  //filename is the same with the wordbook
  QFile file(configFile.dictfile+".rec");
  if(!file.open(QIODevice::WriteOnly))
      return 0;
  QDataStream out(&file);
  for(int i=0;i<dict.num;i++)
    {
      out << dict.words[i].degree;
    }
  file.close();
  return 1;
}

QStringList ReciteWord::getPaths()
{
  QStringList sl;
  sl << configFile.dictfile << configFile.speechpath;
  return sl;
}
void ReciteWord::setPaths(QStringList sl)
{
  configFile.dictfile = sl.at(0);
  configFile.speechpath = sl.at(1);
}
//0 : read dict file error(fatal error)
//2 : read record file error ( not fatal )
//1 : all right
int ReciteWord::initReciteWord()
{
  initOKFlag = false;
  clearAllText();

  QDomDocument doc("mydocument");
  QFile file(configFile.dictfile);
  if(!file.open(QIODevice::ReadOnly))
    return 0;
  if(!doc.setContent(&file)){
    file.close();
    return 0;
  }
  file.close();
  
  //QDomNodeList list = doc.childNodes();
  QDomNodeList list = doc.firstChild().childNodes();	//<item>
  dict.num = 0;
  for(int i=0;i<list.length();i++){
    QDomNodeList itemList = list.item(i).childNodes();	//<word>,<trans>,<phonetic>,<tag>
    QString word = "", trans = "", phonetic = "", example = "";
    for(int j=0;j<itemList.length();j++)	//get word,trans,phonetic (ignore tag)
      {
	QDomNode node = itemList.item(j);
	//node.toElement().text();	//get the text of a node
	//node.nodeName()		//node name (QString)
	if(node.nodeName()=="word")
	  word = node.toElement().text();
	else if(node.nodeName()=="trans")
	  trans = node.toElement().text();
	else if(node.nodeName()=="phonetic")
	  phonetic = node.toElement().text();
	else if(node.nodeName()=="example")
	  example = node.toElement().text();
	//cout << qPrintable(node.nodeName()) << ":" << qPrintable(node.toElement().text()) << endl;
      }
    dict.words[dict.num].word = word;
    dict.words[dict.num].trans = trans;
    dict.words[dict.num].phonetic = phonetic;
    dict.words[dict.num].example = example;
    dict.words[dict.num].degree = DEFAULT_DEGREE;
    dict.num++;
    
    if(dict.num >= MAXNUM_OF_WORDS)	//get no more than this value
      break;
  }

  //get the degree from record file (if no record file, keep default value)
  QFile recfile(configFile.dictfile+".rec");
  if(!recfile.open(QIODevice::ReadOnly))
    return 2;
  QDataStream in(&recfile);
  rememberedCnt = 0;
  for(int i=0;i<dict.num;i++)
    {
      if(in.atEnd() == true)
	break;
      in >> dict.words[i].degree ;		//read float value
      cout << dict.words[i].degree << endl;
      if(dict.words[i].degree <= REMEMBERED_DEGREE)	//count of remembered word
	rememberedCnt++;	
    }
  recfile.close();

  /*  for(int i=0;i<dict.num;i++)
    {
      cout << qPrintable(dict.words[i].word) << endl;
      cout << qPrintable(dict.words[i].phonetic) << endl;
      cout << qPrintable(dict.words[i].trans) << endl;
      sleep(1);
    }
  */
  statisticLabel->setText(" Remembered : " + QString::number(rememberedCnt) + " / " + QString::number(dict.num)) ;
  //  get nextWord();	 ??
  wordIndex = getWordIndex();	//global variable
  wordLine->setText(dict.words[wordIndex].word);
  phoneticLabel->setText(dict.words[wordIndex].phonetic);
  //  transEdit->setText(dict.words[wordIndex].trans);
  //  if() exampleEdit->setText(dict.words[wordIndex].example);
  
  autoSpeechBox->setChecked(configFile.autospeech);
  showExampleBox->setChecked(configFile.showexample);
  exampleEdit->setVisible(configFile.showexample);
  initOKFlag = true;
  return 1;
}

bool ReciteWord::initOK()
{
  return initOKFlag;
}

//get a random index of words
int ReciteWord::getWordIndex()
{
  static int index = 0;
  //  static int lastIndex = -1;
  float sum;
  float random;

  if(dict.num==0)
    return -1;
  sum = 0;
  for(int i=0;i<dict.num;i++)
  //for(int i=0;i<50;i++)
    {
      sum += dict.words[i].degree;
    }
  //generate a float random between [0,sum]
  //  srand(time(NULL)); in constructor function
  random = (float)(rand())/((float)RAND_MAX)*sum;
  float pos = 0;
  int i;
  for(i=0;i<dict.num;i++)
    {
      if( (random >= pos) && (random < pos+dict.words[i].degree) )
	break;
      pos += dict.words[i].degree;
    }
  //i is selected
  //if the same index was selected last time, retry !   how ?  
  //  if(i == lastIndex)
  if(i>=dict.num)
    i = dict.num - 1;	//if random==sum

  cout << i << endl;
  return i;
}
	
void ReciteWord::test()
{
}

void ReciteWord::getSettings()
{
  /*  //  parent.showSettingPage();
  QStringList pathList = settingDialog->showSettings(configFile.dictfile, configFile.speechpath);
  configFile.dictfile = pathList.at(0);	//get from setting page
  configFile.speechpath = pathList.at(1);	//get from setting page,
  */
}

int ReciteWord::readConfigFile()
{
  QFile file(CONFIG_FILE);
  if(!file.open(QIODevice::ReadOnly))
    {
      //go to setting page
      //getSettings();
      return 0;
    }
  else
    {
      QDataStream in(&file);
      in >> configFile.dictfile;		//if at the end of file, how to process ??
      in >> configFile.speechpath;
      in >> configFile.autospeech;
      in >> configFile.showexample;
      file.close();
      backupConfig();
      return 1;
    }
}
void ReciteWord::clearAllText()
{
  wordLine->setText("");
  phoneticLabel->setText("");
  transEdit->setText("");
  exampleEdit->setText("");
  statisticLabel->setText("xxx");
}

ReciteWord::ReciteWord(QWidget *parent)
  : QWidget(parent)
{
  mParent = parent;			//parent

  setStyleSheet("QPushButton{width:200px;height:60px;font: bold normal 24pt 'Courier New'} \
QLineEdit, QTextEdit{width:400px;font:normal normal 24pt 'DejaVu Sans'} \
QLabel#statisticLabel, QLabel#phoneticLabel{font: bold normal 20pt 'Courier New'} \
QCheckBox{font: normal normal 16pt 'Courier New'} \
QCheckBox::indicator{width:32px;height:32px;} \
");

  //setStyleSheet:
  //font : font-weight font-style font-size font-family

  //setGeometry(100,200,300,400);
  //resize(400,600);
  //setFixedSize(400, 500);

  QFont userFont("Courier New", 18, QFont::Normal);//QFont::Bold);

  statisticLabel = new QLabel(tr("statistic"));
  statisticLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
  statisticLabel->setObjectName("statisticLabel");

  wordLine = new QLineEdit;
  //  wordLine->setFont(userFont);
  wordLine->setReadOnly(true);

  phoneticLabel = new QLabel;
  //phoneticLabel->setFont(userFont);
  phoneticLabel->setObjectName("statisticLabel");

  transEdit = new QTextEdit;
  //  transEdit->setFont(userFont);
  transEdit->setReadOnly(true);
  transEdit->setMinimumSize(500, 200);
    
  exampleEdit = new QTextEdit(tr("examples ..."));
  exampleEdit->setReadOnly(true);
  exampleEdit->setMinimumSize(500, 300);
  
  knowBtn = new QPushButton(tr("&Know"));
  unknowBtn = new QPushButton(tr("&unKnow"));
  rightBtn = new QPushButton(tr("&Right"));
  //  rightBtn->setFont(userFont);
  //rightBtn->setMinimumSize(100,60);
  wrongBtn = new QPushButton(tr("&Wrong"));
  nextBtn = new QPushButton(tr("&Next"));

  connect(knowBtn, SIGNAL(clicked()), this, SLOT(know()));
  connect(unknowBtn, SIGNAL(clicked()), this, SLOT(unKnow()));
  connect(rightBtn, SIGNAL(clicked()), this, SLOT(knowRight()));
  connect(wrongBtn, SIGNAL(clicked()), this, SLOT(knowWrong()));
  connect(nextBtn, SIGNAL(clicked()), this, SLOT(nextWord()));
 
  rightBtn->setVisible(false);
  wrongBtn->setVisible(false);
  nextBtn->setVisible(false);


  QHBoxLayout *btnLayout = new QHBoxLayout();
  btnLayout->addWidget(knowBtn);
  btnLayout->addWidget(unknowBtn);
  btnLayout->addWidget(rightBtn);
  btnLayout->addWidget(wrongBtn);
  btnLayout->addWidget(nextBtn);
  //btnLayout->addStretch();

  QPushButton *voiceButton = new QPushButton(QIcon("/usr/local/eTablet/bin/launcher/resources/speaker_64.png"), "");
  voiceButton->setFixedSize(32,32);
  connect(voiceButton, SIGNAL(clicked()), this, SLOT(speech()));

  autoSpeechBox = new QCheckBox;
  connect(autoSpeechBox, SIGNAL(clicked(bool)), this, SLOT(setAutoSpeech(bool)));
  //autoSpeechBox->setMinimumSize(100,100);	//the sqare not changed
  //autoSpeechBox->resize(200,200);		//not available

  QHBoxLayout *voiceLayout = new QHBoxLayout();
  voiceLayout->addWidget(voiceButton);
  voiceLayout->addWidget(autoSpeechBox);

  showExampleBox = new QCheckBox(tr("Example"));
  connect(showExampleBox, SIGNAL(clicked(bool)), this, SLOT(showExampleEdit(bool)));


  QGridLayout *mainLayout = new QGridLayout;
  /*  mainLayout->setSpacing(20);
  mainLayout->setRowStretch(0, 100);
  mainLayout->setRowStretch(7, 100);
  mainLayout->setColumnStretch(0, 100);
  mainLayout->setColumnStretch(3, 100);
  mainLayout->addWidget(statisticLabel, 0, 0, 1, 4);
  mainLayout->addWidget(wordLine, 1, 1);
  mainLayout->addLayout(voiceLayout, 1, 2);	//voiceButton
  mainLayout->addWidget(phoneticLabel, 2, 1);
  mainLayout->addWidget(transEdit, 3, 1, 1, 2, Qt::AlignTop);
  mainLayout->addLayout(btnLayout, 4, 1, 1, 2);
  mainLayout->addWidget(showExampleBox, 5, 1, 1, 2);
  mainLayout->addWidget(exampleEdit, 6, 1, 1, 2);
  setLayout(mainLayout);
  */
  mainLayout->setSpacing(20);
  mainLayout->addWidget(wordLine, 0, 0);
  mainLayout->addLayout(voiceLayout, 0, 1);	//voiceButton
  mainLayout->addWidget(phoneticLabel, 1, 0, 1, 2);
  mainLayout->addWidget(transEdit, 2, 0, 1, 2, Qt::AlignTop);
  mainLayout->addLayout(btnLayout, 3, 0, 1, 2);
  mainLayout->addWidget(showExampleBox, 4, 0, 1, 2);
  mainLayout->addWidget(exampleEdit, 5, 0, 1, 2);

  //create another QGridLayout contain the mainLayout
  /*  QGridLayout *gl = new QGridLayout;
  gl->addWidget(statisticLabel, 0, 0, 1, 3);
  gl->setRowStretch(0, 500);
  gl->setRowStretch(2, 800);
  gl->setColumnStretch(0, 800);
  gl->setColumnStretch(2, 800);
  gl->addLayout(mainLayout, 1, 1);
  setLayout(gl);
  */


  //for before QT 4.5 (toolbar disappear while showFullScreen())
  //show toolbar
  QAction *settingAct= new QAction(tr("&Setting"), this);
  settingAct->setFont(userFont);
  connect(settingAct, SIGNAL(triggered()), parent, SLOT(showSettingPage()));
  QAction *quitAct = new QAction(tr("&Quit"), this);
  quitAct->setFont(userFont);
  connect(quitAct, SIGNAL(triggered()), parent, SLOT(close()));
  QToolBar *tb = new QToolBar;
  tb->addAction(settingAct);
  tb->addSeparator();
  tb->addAction(quitAct);



  QVBoxLayout *vl = new QVBoxLayout;
  vl->addWidget(tb);
  vl->addWidget(statisticLabel);
  vl->addStretch();
  QGridLayout *gl = new QGridLayout;  
  gl->addLayout(vl, 0, 0, 1, 3, Qt::AlignTop);
  gl->setRowStretch(0, 500);
  gl->setRowStretch(2, 800);
  gl->setColumnStretch(0, 800);
  gl->setColumnStretch(2, 800);
  gl->addLayout(mainLayout, 1, 1);
  setLayout(gl);

  //basic initialization
  initOKFlag = false;

  configFile.dictfile = DEFAULT_DICT_FILE;
  configFile.speechpath = DEFAULT_SPEECH_PATH;
  configFile.autospeech = DEFAULT_AUTO_SPEECH;
  configFile.showexample = DEFAULT_SHOW_EXAMPLE;

  backupConfig();	//back up of configFile

  //set show Example checkbox， voice check box (default value)
  autoSpeechBox->setChecked(configFile.autospeech);
  showExampleBox->setChecked(configFile.showexample);
  exampleEdit->setVisible(configFile.showexample);

  clearAllText();

  srand(time(NULL));
}


ReciteWord::~ReciteWord()
{
  if(initOK() == true)
    record();			//save data

  //save the config file if parameters modified
  if(configFile.dictfile != configFileBak.dictfile ||  configFile.speechpath != configFileBak.speechpath ||  configFile.autospeech != configFileBak.autospeech ||  configFile.showexample != configFileBak.showexample)
    {
      //cout << "save params"<< endl;
      QFile file(CONFIG_FILE);
      if(file.open(QIODevice::WriteOnly))
	{
	  QDataStream out(&file);
	  out << configFile.dictfile;	// fullname of dict (workpath+dictname)	//QString
	  out << configFile.speechpath;	// path of speech 			//QString
	  out << configFile.autospeech;	// auto speech or not			//bool
	  out << configFile.showexample;// display example or not	//bool
	  file.close();
	}
    }
  //else ignore
}
